"""
摄像头处理模块
"""

import cv2
import numpy as np
from typing import Optional, Tuple
from config import CAMERA_CONFIG

class CameraHandler:
    """摄像头处理类"""
    
    def __init__(self, camera_id: int = None):
        """
        初始化摄像头
        
        Args:
            camera_id: 摄像头ID，默认使用配置文件中的设置
        """
        self.camera_id = camera_id if camera_id is not None else CAMERA_CONFIG['camera_id']
        self.width = CAMERA_CONFIG['width']
        self.height = CAMERA_CONFIG['height']
        self.fps = CAMERA_CONFIG['fps']
        
        self.cap = None
        self.is_opened = False
        
    def open_camera(self) -> bool:
        """
        打开摄像头
        
        Returns:
            是否成功打开
        """
        try:
            self.cap = cv2.VideoCapture(self.camera_id)
            
            if not self.cap.isOpened():
                print(f"无法打开摄像头 {self.camera_id}")
                return False
            
            # 设置摄像头参数
            self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.width)
            self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.height)
            self.cap.set(cv2.CAP_PROP_FPS, self.fps)
            
            # 验证设置是否成功
            actual_width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            actual_height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            actual_fps = int(self.cap.get(cv2.CAP_PROP_FPS))
            
            print(f"摄像头已打开: {actual_width}x{actual_height} @{actual_fps}fps")
            
            self.is_opened = True
            return True
            
        except Exception as e:
            print(f"打开摄像头时发生错误: {e}")
            return False
    
    def close_camera(self) -> None:
        """关闭摄像头"""
        if self.cap is not None:
            self.cap.release()
            self.is_opened = False
            print("摄像头已关闭")
    
    def read_frame(self) -> Tuple[bool, Optional[np.ndarray]]:
        """
        读取一帧图像
        
        Returns:
            (是否成功, 图像数据)
        """
        if not self.is_opened or self.cap is None:
            return False, None
        
        ret, frame = self.cap.read()
        
        if not ret:
            print("无法读取摄像头帧")
            return False, None
        
        # 水平翻转图像（镜像效果）
        frame = cv2.flip(frame, 1)
        
        return True, frame
    
    def get_camera_info(self) -> dict:
        """
        获取摄像头信息
        
        Returns:
            摄像头信息字典
        """
        if not self.is_opened or self.cap is None:
            return {}
        
        info = {
            'width': int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
            'height': int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)),
            'fps': int(self.cap.get(cv2.CAP_PROP_FPS)),
            'brightness': self.cap.get(cv2.CAP_PROP_BRIGHTNESS),
            'contrast': self.cap.get(cv2.CAP_PROP_CONTRAST),
            'saturation': self.cap.get(cv2.CAP_PROP_SATURATION),
            'hue': self.cap.get(cv2.CAP_PROP_HUE)
        }
        
        return info
    
    def set_camera_property(self, property_id: int, value: float) -> bool:
        """
        设置摄像头属性
        
        Args:
            property_id: 属性ID
            value: 属性值
        
        Returns:
            是否设置成功
        """
        if not self.is_opened or self.cap is None:
            return False
        
        return self.cap.set(property_id, value)
    
    def adjust_brightness(self, brightness: float) -> bool:
        """
        调整亮度
        
        Args:
            brightness: 亮度值 (0-1)
        
        Returns:
            是否调整成功
        """
        return self.set_camera_property(cv2.CAP_PROP_BRIGHTNESS, brightness)
    
    def adjust_contrast(self, contrast: float) -> bool:
        """
        调整对比度
        
        Args:
            contrast: 对比度值 (0-1)
        
        Returns:
            是否调整成功
        """
        return self.set_camera_property(cv2.CAP_PROP_CONTRAST, contrast)
    
    def auto_adjust_exposure(self) -> bool:
        """
        自动调整曝光
        
        Returns:
            是否调整成功
        """
        return self.set_camera_property(cv2.CAP_PROP_AUTO_EXPOSURE, 0.25)
    
    def test_camera(self, duration: int = 5) -> bool:
        """
        测试摄像头
        
        Args:
            duration: 测试持续时间（秒）
        
        Returns:
            测试是否成功
        """
        if not self.open_camera():
            return False
        
        print(f"开始测试摄像头 {duration} 秒...")
        
        frame_count = 0
        start_time = cv2.getTickCount()
        
        while True:
            ret, frame = self.read_frame()
            
            if not ret:
                print("读取帧失败")
                break
            
            frame_count += 1
            
            # 显示帧数信息
            cv2.putText(frame, f"Frame: {frame_count}", (10, 30), 
                       cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
            
            cv2.imshow("Camera Test", frame)
            
            # 检查是否超时
            current_time = cv2.getTickCount()
            elapsed_time = (current_time - start_time) / cv2.getTickFrequency()
            
            if elapsed_time >= duration:
                break
            
            # 按ESC键退出
            if cv2.waitKey(1) & 0xFF == 27:
                break
        
        # 计算实际帧率
        actual_fps = frame_count / elapsed_time
        print(f"测试完成: {frame_count} 帧, 实际FPS: {actual_fps:.2f}")
        
        cv2.destroyAllWindows()
        self.close_camera()
        
        return True
    
    def capture_image(self, filename: str) -> bool:
        """
        拍照保存
        
        Args:
            filename: 保存文件名
        
        Returns:
            是否保存成功
        """
        ret, frame = self.read_frame()
        
        if not ret:
            print("无法拍照")
            return False
        
        success = cv2.imwrite(filename, frame)
        
        if success:
            print(f"图像已保存: {filename}")
        else:
            print(f"保存图像失败: {filename}")
        
        return success
    
    def __enter__(self):
        """上下文管理器入口"""
        self.open_camera()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """上下文管理器出口"""
        self.close_camera()

def list_available_cameras() -> list:
    """
    列出可用的摄像头
    
    Returns:
        可用摄像头ID列表
    """
    available_cameras = []
    
    # 测试前10个摄像头ID
    for i in range(10):
        cap = cv2.VideoCapture(i)
        if cap.isOpened():
            available_cameras.append(i)
            cap.release()
    
    return available_cameras

def get_optimal_camera_settings(camera_id: int = 0) -> dict:
    """
    获取最佳摄像头设置
    
    Args:
        camera_id: 摄像头ID
    
    Returns:
        最佳设置字典
    """
    cap = cv2.VideoCapture(camera_id)
    
    if not cap.isOpened():
        return {}
    
    # 获取支持的分辨率
    resolutions = [
        (1920, 1080),
        (1280, 720),
        (640, 480),
        (320, 240)
    ]
    
    supported_resolutions = []
    
    for width, height in resolutions:
        cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
        
        actual_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        actual_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        
        if actual_width == width and actual_height == height:
            supported_resolutions.append((width, height))
    
    # 获取支持的帧率
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
    
    fps_values = [60, 30, 15, 10]
    supported_fps = []
    
    for fps in fps_values:
        cap.set(cv2.CAP_PROP_FPS, fps)
        actual_fps = int(cap.get(cv2.CAP_PROP_FPS))
        
        if actual_fps >= fps * 0.8:  # 允许20%的误差
            supported_fps.append(fps)
    
    cap.release()
    
    optimal_settings = {
        'supported_resolutions': supported_resolutions,
        'supported_fps': supported_fps,
        'recommended_resolution': supported_resolutions[0] if supported_resolutions else (640, 480),
        'recommended_fps': supported_fps[0] if supported_fps else 30
    }
    
    return optimal_settings

if __name__ == "__main__":
    # 测试代码
    print("检测可用摄像头...")
    cameras = list_available_cameras()
    print(f"可用摄像头: {cameras}")
    
    if cameras:
        print(f"\n测试摄像头 {cameras[0]}...")
        
        # 获取最佳设置
        settings = get_optimal_camera_settings(cameras[0])
        print(f"最佳设置: {settings}")
        
        # 测试摄像头
        camera = CameraHandler(cameras[0])
        camera.test_camera(5)
    else:
        print("未找到可用摄像头") 